package hotn

import (
	"errors"
	"fmt"
	"image"
	"image/draw"
	"image/png"
	"log"
	"os"
	"path/filepath"
	"slices"
	"strconv"
	"strings"

	_ "image/jpeg"

	"github.com/disintegration/imaging"
	"github.com/pdfcpu/pdfcpu/pkg/api"
	"github.com/pdfcpu/pdfcpu/pkg/pdfcpu"
	"github.com/pdfcpu/pdfcpu/pkg/pdfcpu/model"
	"github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types"
)

// 定义错误类型常量
var (
	// ErrInvalidConfig 配置参数无效错误
	ErrInvalidConfig = errors.New("配置参数无效")
	// ErrFileNotFound 文件不存在错误
	ErrFileNotFound = errors.New("文件不存在")
	// ErrFileAccess 文件访问权限错误
	ErrFileAccess = errors.New("文件访问权限不足")
	// ErrImageProcessing 图片处理错误
	ErrImageProcessing = errors.New("图片处理失败")
	// ErrPDFProcessing PDF处理错误
	ErrPDFProcessing = errors.New("PDF处理失败")
	// ErrInvalidRange 页面范围无效错误
	ErrInvalidRange = errors.New("页面范围无效")
)

// Stamp 印章配置结构体
// 功能: 定义单个印章的所有配置参数
// 字段说明:
//   - StampFile: 印章图片文件路径
//   - Position: 印章位置锚点
//   - Offset: 印章偏移量
//   - Opacity: 印章透明度
//   - Rotation: 印章旋转角度
//   - 印章高度: 自动从图片文件获取
//   - RidingInterval: 骑缝章间隔页数
//   - PageRangeType: 页面范围类型
//   - PageSelector: 页面选择器
type Stamp struct {
	StampFile           string              // 印章图片文件路径
	RidingStampPosition RidingStampPosition // 骑缝章位置(l, r, t, b)
	Position            string              // 印章位置 (l, c, r, tl, tc, tr, bl, bc, br)。坐标轴的零点
	Offset              []int32             // 印章偏移量 [x, y]
	Height              float64             // 印章高度，单位：POINT（1点 = 1/72英寸）。会用来自动计算印章的大小和骑缝章切图
	Width               float64             // 印章宽度，单位：POINT（1点 = 1/72英寸）。会用来自动计算印章的大小和骑缝章切图
	Opacity             float64             // 印章透明度 (0-1)
	Rotation            float64             // 印章旋转角度（度数，-180到180）
	RidingInterval      int                 // 骑缝章间隔页数，0表示单个骑缝章覆盖所有页面
	PageRangeType       PageRangeType       // 页面范围类型（向后兼容，建议使用SetPageRange方法）
	PageSelector        PageSelector        // 页面选择器（建议使用SetPageSelector方法）
}

// StampConfig 盖章配置结构体
// 功能: 定义PDF盖章操作的所有配置参数
// 字段说明:
//   - InputFile: 输入PDF文件路径
//   - OutputFile: 输出PDF文件路径
//   - Stamps: 印章配置列表（支持多印章）
//
// 页面选择说明：
// - 推荐使用 SetPageSelector() 方法设置自定义页面选择
// - 或使用 SetPageRange() 方法设置基础页面范围
// - 两种方式互斥，后设置的会覆盖前面的设置
type StampConfig struct {
	InputFile  string  // 输入PDF文件路径
	OutputFile string  // 输出PDF文件路径
	Stamps     []Stamp // 印章配置列表（支持多印章）
}

// NewStamp 创建默认的印章配置
// 功能: 初始化印章配置对象，设置合理的默认值
// 参数:
//   - stampFile: 印章图片文件路径
//
// 返回值:
//   - *Stamp: 默认印章配置对象
func NewStamp(stampFile string) *Stamp {
	return &Stamp{
		StampFile:      stampFile,
		Position:       "br",          // 右下角
		Offset:         []int32{0, 0}, // 默认无偏移
		Width:          100,
		Opacity:        0.8,          // 80%透明度
		Rotation:       0.0,          // 默认不旋转
		RidingInterval: 0,            // 默认单个骑缝章覆盖所有页面
		PageRangeType:  PageRangeAll, // 默认所有页面
	}
}

// NewStampConfig 创建默认的盖章配置
// 功能: 初始化盖章配置对象，设置合理的默认值
// 返回值:
//   - *StampConfig: 默认配置对象
func NewStampConfig() *StampConfig {
	return &StampConfig{
		Stamps: []Stamp{}, // 空的印章列表
	}
}

// Stamp结构体的Set方法

// SetPosition 设置印章位置
func (s *Stamp) SetPosition(position string) *Stamp {
	s.Position = position
	return s
}

// SetOffset 设置印章偏移量
func (s *Stamp) SetOffset(x, y int32) *Stamp {
	s.Offset = []int32{x, y}
	return s
}

// SetHeight 设置印章高度
func (s *Stamp) SetHeight(height float64) *Stamp {
	s.Height = height
	return s
}

// SetWidth 设置印章宽度
func (s *Stamp) SetWidth(width float64) *Stamp {
	s.Width = width
	return s
}

// SetOpacity 设置印章透明度
func (s *Stamp) SetOpacity(opacity float64) *Stamp {
	s.Opacity = opacity
	return s
}

// SetRotation 设置印章旋转角度
func (s *Stamp) SetRotation(rotation float64) *Stamp {
	s.Rotation = rotation
	return s
}

// SetStampHeight 方法已移除，印章高度现在自动从图片文件获取

// SetRidingInterval 设置骑缝章间隔页数
func (s *Stamp) SetRidingInterval(interval int) *Stamp {
	s.RidingInterval = interval
	return s
}

// SetPageRange 设置页面范围类型
func (s *Stamp) SetPageRange(rangeType PageRangeType) *Stamp {
	s.PageRangeType = rangeType
	s.PageSelector = PageSelector{} // 清空PageSelector
	return s
}

// SetPageSelector 设置页面选择器
func (s *Stamp) SetPageSelector(selector PageSelector) *Stamp {
	s.PageSelector = selector
	s.PageRangeType = PageRangeAll // 重置为默认值
	return s
}

// SetRidingStampPosition
func (s *Stamp) SetRidingStampPosition(position RidingStampPosition) *Stamp {
	s.RidingStampPosition = position
	return s
}

// SetInputFile 设置输入PDF文件路径
// 功能: 设置输入PDF文件路径
// 参数:
//   - inputFile: 输入PDF文件路径
//
// 返回值:
//   - *StampConfig: 配置对象本身，支持链式调用
func (c *StampConfig) SetInputFile(inputFile string) *StampConfig {
	c.InputFile = inputFile
	return c
}

// SetOutputFile 设置输出PDF文件路径
// 功能: 设置输出PDF文件路径
// 参数:
//   - outputFile: 输出PDF文件路径
//
// 返回值:
//   - *StampConfig: 配置对象本身，支持链式调用
func (c *StampConfig) SetOutputFile(outputFile string) *StampConfig {
	c.OutputFile = outputFile
	return c
}

// AddStamp 添加印章到配置中
// 功能: 向StampConfig中添加一个新的印章配置
// 参数:
//   - stamp: 印章配置对象
//
// 返回值:
//   - *StampConfig: 配置对象本身，支持链式调用
func (c *StampConfig) AddStamp(stamp Stamp) *StampConfig {
	c.Stamps = append(c.Stamps, stamp)
	return c
}

// ClearStamps 清空所有印章配置
// 功能: 清空StampConfig中的所有印章配置
// 返回值:
//   - *StampConfig: 配置对象本身，支持链式调用
func (c *StampConfig) ClearStamps() *StampConfig {
	c.Stamps = []Stamp{}
	return c
}

// GetStampCount 获取印章数量
// 功能: 获取当前配置中的印章数量
// 返回值:
//   - int: 印章数量
func (c *StampConfig) GetStampCount() int {
	return len(c.Stamps)
}

// GetStamp 获取指定索引的印章配置
// 功能: 获取指定索引位置的印章配置
// 参数:
//   - index: 印章索引（从0开始）
//
// 返回值:
//   - *Stamp: 印章配置对象指针，如果索引无效则返回nil
func (c *StampConfig) GetStamp(index int) *Stamp {
	if index < 0 || index >= len(c.Stamps) {
		return nil
	}
	return &c.Stamps[index]
}

// RemoveStamp 移除指定索引的印章配置
// 功能: 移除指定索引位置的印章配置
// 参数:
//   - index: 印章索引（从0开始）
//
// 返回值:
//   - *StampConfig: 配置对象本身，支持链式调用
//   - error: 如果索引无效则返回错误
func (c *StampConfig) RemoveStamp(index int) (*StampConfig, error) {
	if index < 0 || index >= len(c.Stamps) {
		return c, fmt.Errorf("%w: 印章索引超出范围: %d，有效范围: [0-%d]", ErrInvalidConfig, index, len(c.Stamps)-1)
	}

	// 移除指定索引的印章
	c.Stamps = append(c.Stamps[:index], c.Stamps[index+1:]...)
	return c, nil
}

// AddNormalStamp 添加普通盖章
// 功能: 为PDF文件的指定页面添加普通印章，支持多种位置和样式配置，支持多印章
// 注意：纳鲁之锤盖章不支持直接写宽高，只能靠 scale 控制。工具会根据用户给定的印章宽度自动计算scale（相对页宽/高）
// 参数:
//   - config: 盖章配置对象
//
// 返回值:
//   - error: 处理过程中的错误信息
//
// 异常: 文件读写失败、配置参数无效、PDF处理失败
func AddNormalStamp(config *StampConfig) error {
	// 1. 验证配置参数
	if err := validateConfig(config); err != nil {
		return fmt.Errorf("配置验证失败: %w", err)
	}

	// 2. 读取PDF文件上下文
	ctx, err := api.ReadContextFile(config.InputFile)
	if err != nil {
		return fmt.Errorf("%w: 读取PDF文件失败: %v", ErrPDFProcessing, err)
	}

	// 验证PDF页数
	if ctx.PageCount <= 0 {
		return fmt.Errorf("%w: PDF文件页数无效: %d", ErrPDFProcessing, ctx.PageCount)
	}

	log.Printf("PDF文件信息: 总页数=%d", ctx.PageCount)

	// 3. 处理多印章
	// 多印章模式
	return addMultipleNormalStamps(config, ctx)
}

// addMultipleNormalStamps 添加多个普通印章
func addMultipleNormalStamps(config *StampConfig, ctx *model.Context) error {
	currentFile := config.InputFile
	var allTempFiles []string // 记录所有临时文件，用于最后清理

	// 逐个处理每个印章
	for stampIndex, stamp := range config.Stamps {
		// 根据印章的页面选择器确定要处理的页面
		var filteredPages []int
		var err error
		if !stamp.PageSelector.IsEmpty() {
			filteredPages, err = filterNormalStampPagesBySelector(ctx.PageCount, stamp.PageSelector)
		} else {
			// 使用印章的PageRangeType
			filteredPages, err = filterPagesByRange(ctx.PageCount, stamp.PageRangeType)
		}
		// 如果页面过滤失败，跳过当前印章
		if err != nil {
			log.Println(fmt.Errorf("第%d个印章页面过滤失败: %w", stampIndex+1, err))
			continue
		}

		// 转换为字符串数组供pdfcpu使用
		var pageRange []string
		for _, page := range filteredPages {
			pageRange = append(pageRange, strconv.Itoa(page))
		}

		// 如果没有需要处理的页面，跳过当前印章
		if len(pageRange) == 0 {
			log.Printf("第%d个印章没有需要处理的页面，跳过", stampIndex+1)
			continue
		}

		// 构建印章配置字符串，处理Offset数组可能为空的情况
		var offsetX, offsetY int32
		if len(stamp.Offset) >= 2 {
			offsetX = stamp.Offset[0]
			offsetY = stamp.Offset[1]
		}
		scaleRel := stamp.Width / A4PaperWidthPoints
		desc := fmt.Sprintf("pos:%s, off:%d %d, scale:%.4f rel, op:%.2f, rot:%.1f",
			stamp.Position, offsetX, offsetY, scaleRel, stamp.Opacity, stamp.Rotation)

		// 解析印章水印配置
		wm, err := pdfcpu.ParseImageWatermarkDetails(stamp.StampFile, desc, true, types.POINTS)
		if err != nil {
			return fmt.Errorf("%w: 解析第%d个印章配置失败: %v", ErrPDFProcessing, stampIndex+1, err)
		}

		// 确定输出文件路径
		var outputFile string
		if stampIndex == len(config.Stamps)-1 {
			// 最后一个印章，直接输出到目标文件
			outputFile = config.OutputFile
		} else {
			// 其他情况创建临时文件
			outputFile = fmt.Sprintf("temp_normal_stamp_%d.pdf", stampIndex+1)
			allTempFiles = append(allTempFiles, outputFile)
		}

		// 添加水印到指定页面
		err = api.AddWatermarksFile(currentFile, outputFile, pageRange, wm, nil)
		if err != nil {
			return fmt.Errorf("%w: 添加第%d个印章失败: %v", ErrPDFProcessing, stampIndex+1, err)
		}

		// 更新当前处理文件
		currentFile = outputFile

		log.Printf("第%d个印章处理完成，共处理%d页", stampIndex+1, len(pageRange))
	}

	// 清理所有临时文件
	for _, tempFile := range allTempFiles {
		if err := os.Remove(tempFile); err != nil {
			log.Printf("警告: 清理临时文件失败 %s: %v", tempFile, err)
		}
	}

	// 验证输出文件是否成功创建
	if err := validateOutputFile(config.OutputFile); err != nil {
		return err
	}

	log.Printf("多印章普通盖章处理完成，共处理%d个印章", len(config.Stamps))
	return nil
}

// RidingStampGroup 骑缝章分组信息
type RidingStampGroup struct {
	StartPage int // 起始页码
	EndPage   int // 结束页码
	Pages     int // 该组页数
}

// AddRidingStamp 添加骑缝章
// 功能: 使用图像切分技术实现真正的骑缝章效果，支持多骑缝章分组和页面范围选择，支持多印章
// 参数:
//   - config: 盖章配置对象
//
// 注意：纳鲁之锤盖章不支持直接写宽高，只能靠 scale 控制。工具会根据用户给定的印章宽度自动计算scale（相对页宽/高）
//
// 返回值:
//   - error: 处理过程中的错误信息
//
// 实现原理:
//  1. 获取PDF总页数
//  2. 验证骑缝章页数条件：
//     - 奇数页盖章：PDF总页数必须大于2*x-1（x为间隔页数）
//     - 偶数页盖章：PDF总页数必须大于等于2*x
//     - 所有页盖章：PDF总页数必须大于等于x
//     如果条件不满足，直接复制源文件到输出文件，不做任何处理
//  3. 根据PageRangeType过滤页面
//  4. 使用优化的分组算法计算骑缝章分组
//  5. 为每个分组计算防重叠的位置偏移
//  6. 每个分组内将印章图片垂直切分成N个片段(N=该组页数)
//  7. 每页使用对应的印章片段作为水印
//
// 异常: 文件读写失败、配置参数无效、图片处理失败
func AddRidingStamp(config *StampConfig) error {
	// 1. 验证配置参数
	if err := validateConfig(config); err != nil {
		return fmt.Errorf("配置验证失败: %w", err)
	}

	// 2. 读取PDF文件上下文，获取总页数
	ctx, err := api.ReadContextFile(config.InputFile)
	if err != nil {
		return fmt.Errorf("%w: 读取PDF文件失败: %v", ErrPDFProcessing, err)
	}
	totalPages := ctx.PageCount

	if totalPages <= 0 {
		return fmt.Errorf("%w: PDF文件页数无效: %d", ErrPDFProcessing, totalPages)
	}
	if totalPages > 1000 {
		return fmt.Errorf("%w: PDF页数过多(>1000): %d", ErrPDFProcessing, totalPages)
	}

	log.Printf("PDF文件信息: 总页数=%d", ctx.PageCount)

	// 3. 验证骑缝章页数条件，收集满足条件的印章
	validStamps := make([]Stamp, 0, len(config.Stamps))

	for stampIndex, stamp := range config.Stamps {
		// 确定页面范围类型
		var rangeType PageRangeType
		if !stamp.PageSelector.IsEmpty() {
			rangeType = stamp.PageSelector.RangeType
		} else {
			rangeType = stamp.PageRangeType
		}

		// 验证页数条件
		ok, err := validateRidingStampPageCondition(ctx.PageCount, rangeType, stamp.RidingInterval)
		if err != nil {
			return fmt.Errorf("第%d个印章页数条件验证失败: %w", stampIndex+1, err)
		}

		// 只保留满足条件的印章
		if ok {
			validStamps = append(validStamps, stamp)
		}
	}

	// 更新印章列表
	config.Stamps = validStamps

	// 4. 处理多印章或单印章（向后兼容）
	// 多印章模式
	return addMultipleRidingStamps(config, ctx)
}

// addMultipleRidingStamps 添加多个骑缝章
func addMultipleRidingStamps(config *StampConfig, ctx *model.Context) error {
	totalPages := ctx.PageCount
	currentFile := config.InputFile
	var allTempFiles []string // 记录所有临时文件，用于最后清理

	// 逐个处理每个印章
	for stampIndex, stamp := range config.Stamps {
		// 根据印章的页面选择器过滤页面
		var filteredPages []int
		var err error
		if !stamp.PageSelector.IsEmpty() {
			filteredPages, err = filterPagesBySelector(totalPages, stamp.PageSelector)
		} else {
			// 使用印章的PageRangeType
			filteredPages, err = filterPagesByRange(totalPages, stamp.PageRangeType)
		}
		// 如果页面过滤失败，跳过当前印章
		if err != nil {
			log.Println(fmt.Errorf("第%d个印章页面过滤失败: %w", stampIndex+1, err))
			continue
		}
		filteredPageCount := len(filteredPages)

		// 使用优化的分组算法计算骑缝章分组
		groups, err := calculateOptimizedRidingStampGroups(filteredPageCount, stamp.RidingInterval)
		if err != nil {
			return fmt.Errorf("第%d个印章计算优化骑缝章分组失败: %w", stampIndex+1, err)
		}

		log.Printf("开始处理第%d个印章的骑缝章，过滤后页数: %d，分组数: %d，间隔: %d",
			stampIndex+1, filteredPageCount, len(groups), stamp.RidingInterval)

		// 逐个处理当前印章的每个骑缝章分组
		handledPages := make(map[int]struct{}) // 用来统计处理过的页
		for groupIndex, group := range groups {
			// 为当前分组切分印章图片
			segmentPaths, err := splitStampImageForTool(stamp.StampFile, stamp.RidingStampPosition, group.Pages, stamp.Rotation)
			if err != nil {
				return fmt.Errorf("第%d个印章切分第%d组印章图片失败: %w", stampIndex+1, groupIndex+1, err)
			}
			defer func(paths []string) {
				// 清理当前分组的临时切分图片文件
				for _, path := range paths {
					os.Remove(path)
				}
			}(segmentPaths)

			// 为当前分组的每一页添加对应的印章片段
			groupOffset := stamp.Offset
			for pageIndex := 0; pageIndex < group.Pages; pageIndex++ {
				// 映射到过滤后的实际页面
				filteredPageIndex := group.StartPage + pageIndex - 1 // 转换为0基索引
				if filteredPageIndex >= len(filteredPages) {
					return fmt.Errorf("%w: 页面索引超出范围: %d >= %d", ErrInvalidRange, filteredPageIndex, len(filteredPages))
				}
				actualPage := filteredPages[filteredPageIndex] // 获取原始PDF中的实际页码
				segmentFile := segmentPaths[pageIndex]

				// 如果某页已经被处理过，则证明该页已经存在了印章
				// 再次增加印章时，要进行偏移来规避重合问题
				if _, ok := handledPages[actualPage]; ok {
					// 计算当前分组的防重叠位置偏移
					groupOffset, err = calculateGroupPosition(groupIndex, stamp.Offset, stamp.Width, stamp.Height, stamp.RidingStampPosition)
					if err != nil {
						return fmt.Errorf("第%d个印章计算第%d组位置偏移失败: %w", stampIndex+1, groupIndex+1, err)
					}

					log.Printf("处理第%d个印章的第%d个骑缝章分组: 页面%d-%d (共%d页)，位置偏移: [%d, %d]",
						stampIndex+1, groupIndex+1, group.StartPage, group.EndPage, group.Pages, groupOffset[0], groupOffset[1])
				}

				// 使用分组特定的偏移量构建印章配置字符串
				// 注意：旋转已在图片预处理阶段完成，此处不再设置旋转角度
				// 根据骑缝章位置计算正确的缩放比例
				var scaleRel float64
				switch stamp.RidingStampPosition {
				case RidingStampPositionLeft, RidingStampPositionRight:
					scaleRel = stamp.Height / A4PaperHeightPoints
				case RidingStampPositionTop, RidingStampPositionBottom:
					scaleRel = stamp.Width / A4PaperWidthPoints
				default:
					// 默认情况
					scaleRel = stamp.Width / A4PaperWidthPoints
				}
				desc := fmt.Sprintf("pos:%s, off:%d %d, scale:%.9f rel, op:%.2f, rot:0",
					stamp.Position, groupOffset[0], groupOffset[1], scaleRel, stamp.Opacity)

				// 解析印章水印配置
				wm, err := pdfcpu.ParseImageWatermarkDetails(segmentFile, desc, true, types.POINTS)
				if err != nil {
					return fmt.Errorf("%w: 第%d个印章解析第%d组第%d页印章配置失败: %v", ErrPDFProcessing, stampIndex+1, groupIndex+1, actualPage, err)
				}

				// 确定输出文件路径
				var outputFile string
				if stampIndex == len(config.Stamps)-1 && groupIndex == len(groups)-1 && pageIndex == group.Pages-1 {
					// 最后一个印章的最后一个分组的最后一页，直接输出到目标文件
					outputFile = config.OutputFile
				} else {
					// 其他情况创建临时文件
					outputFile = fmt.Sprintf("temp_multi_riding_s%d_g%d_p%d.pdf", stampIndex+1, groupIndex+1, actualPage)
					allTempFiles = append(allTempFiles, outputFile)
				}

				// 为当前页添加水印
				err = api.AddWatermarksFile(currentFile, outputFile, []string{fmt.Sprintf("%d", actualPage)}, wm, nil)
				if err != nil {
					return fmt.Errorf("%w: 第%d个印章添加第%d组第%d页印章失败: %v", ErrPDFProcessing, stampIndex+1, groupIndex+1, actualPage, err)
				}

				// 更新当前处理文件
				currentFile = outputFile

				handledPages[actualPage] = struct{}{}
				log.Printf("第%d个印章第%d组第%d页(实际页面%d)骑缝章处理完成，使用片段: %s",
					stampIndex+1, groupIndex+1, pageIndex+1, actualPage, filepath.Base(segmentFile))
			}
		}
	}

	// 清理所有临时文件
	for _, tempFile := range allTempFiles {
		if err := os.Remove(tempFile); err != nil {
			log.Printf("警告: 清理临时文件失败 %s: %v", tempFile, err)
		}
	}

	// 验证输出文件是否成功创建
	if err := validateOutputFile(config.OutputFile); err != nil {
		return err
	}

	log.Printf("多印章骑缝章处理完成，共处理%d个印章", len(config.Stamps))
	return nil
}

// validateRidingStampPageCondition 验证骑缝章页数条件
// 功能: 检查PDF页数是否满足骑缝章的最小页数要求
// 参数:
//   - totalPages: PDF总页数
//   - rangeType: 页面范围类型
//   - interval: 骑缝章间隔页数
//
// 返回值:
//   - bool: 是否满足条件
//   - error: 验证过程中的错误信息
//
// 验证规则:
//   - 奇数页盖章：PDF总页数必须大于2*x-1（x为间隔页数）
//   - 偶数页盖章：PDF总页数必须大于等于2*x
//   - 所有页盖章：PDF总页数必须大于等于x
func validateRidingStampPageCondition(totalPages int, rangeType PageRangeType, interval int) (bool, error) {
	if totalPages <= 0 {
		return false, fmt.Errorf("%w: 总页数必须大于0，当前值: %d", ErrInvalidRange, totalPages)
	}
	if interval < 0 {
		return false, fmt.Errorf("%w: 间隔页数必须大于等于0，当前值: %d", ErrInvalidConfig, interval)
	}

	switch rangeType {
	case PageRangeOdd:
		// 奇数页盖章：PDF总页数必须大于2*x-1
		minPages := 2*interval - 1
		if totalPages <= minPages {
			log.Printf("奇数页骑缝章条件不满足: 总页数=%d, 间隔=%d, 最小需要页数=%d", totalPages, interval, minPages+1)
			return false, nil
		}
	case PageRangeEven:
		// 偶数页盖章：PDF总页数必须大于等于2*x
		minPages := 2 * interval
		if totalPages < minPages {
			log.Printf("偶数页骑缝章条件不满足: 总页数=%d, 间隔=%d, 最小需要页数=%d", totalPages, interval, minPages)
			return false, nil
		}
	case PageRangeAll:
		// 所有页盖章：PDF总页数必须大于等于x
		if totalPages < interval {
			log.Printf("所有页骑缝章条件不满足: 总页数=%d, 间隔=%d", totalPages, interval)
			return false, nil
		}
	default:
		// 其他情况（首页、尾页等）不需要特殊验证
		return true, nil
	}

	log.Printf("骑缝章页数条件验证通过: 总页数=%d, 范围类型=%s, 间隔=%d", totalPages, rangeType.String(), interval)
	return true, nil
}

// validateConfig 验证配置参数的有效性
// 功能: 检查配置参数是否合法，确保后续处理的正确性
// 参数:
//   - config: 盖章配置对象
//
// 返回值:
//   - error: 验证失败时的错误信息
func validateConfig(config *StampConfig) error {
	// 检查必需参数
	if config.InputFile == "" {
		return fmt.Errorf("%w: 输入文件路径不能为空", ErrInvalidConfig)
	}
	if config.OutputFile == "" {
		return fmt.Errorf("%w: 输出文件路径不能为空", ErrInvalidConfig)
	}
	if len(config.Stamps) == 0 {
		return fmt.Errorf("%w: 印章配置不能为空", ErrInvalidConfig)
	}
	for _, stamp := range config.Stamps {
		if stamp.StampFile == "" {
			return fmt.Errorf("%w: 印章文件路径不能为空", ErrInvalidConfig)
		}
		if stamp.Width <= 0 {
			return fmt.Errorf("%w: 印章宽度必须大于0，当前值: %.2f", ErrInvalidConfig, stamp.Width)
		}
		if stamp.Opacity < 0 || stamp.Opacity > 1 {
			return fmt.Errorf("%w: 透明度必须在0-1之间，当前值: %.2f", ErrInvalidConfig, stamp.Opacity)
		}
		if stamp.Rotation < -180 || stamp.Rotation > 180 {
			return fmt.Errorf("%w: 旋转角度必须在-180到180度之间，当前值: %.1f", ErrInvalidConfig, stamp.Rotation)
		}

		// 检查印章文件是否存在和访问权限
		if err := validateFileAccess(stamp.StampFile, "印章文件"); err != nil {
			return err
		}

		// 检查位置参数
		validPositions := map[string]bool{
			"l": true, "c": true, "r": true,
			"tl": true, "tc": true, "tr": true,
			"bl": true, "bc": true, "br": true,
		}
		if !validPositions[stamp.Position] {
			return fmt.Errorf("%w: 无效的位置参数: %s，有效值: l, c, r, tl, tc, tr, bl, bc, br", ErrInvalidConfig, stamp.Position)
		}

	}

	// 检查文件是否存在和访问权限
	if err := validateFileAccess(config.InputFile, "输入文件"); err != nil {
		return err
	}

	// 检查输出目录是否可写
	if err := validateOutputPath(config.OutputFile); err != nil {
		return err
	}

	return nil
}

// validateFileAccess 验证文件是否存在且可访问
// 功能: 检查文件的存在性和可读性
// 参数:
//   - filePath: 文件路径
//   - fileType: 文件类型描述
//
// 返回值:
//   - error: 验证失败时的错误信息
func validateFileAccess(filePath, fileType string) error {
	// 检查文件是否存在
	info, err := os.Stat(filePath)
	if os.IsNotExist(err) {
		return fmt.Errorf("%w: %s不存在: %s", ErrFileNotFound, fileType, filePath)
	}
	if err != nil {
		return fmt.Errorf("%w: 无法访问%s: %s, 错误: %v", ErrFileAccess, fileType, filePath, err)
	}

	// 检查是否为文件（非目录）
	if info.IsDir() {
		return fmt.Errorf("%w: %s路径指向目录而非文件: %s", ErrInvalidConfig, fileType, filePath)
	}

	// 检查文件扩展名
	if err := validateFileExtension(filePath, fileType); err != nil {
		return err
	}

	// 检查文件大小（放在最后，避免掩盖其他错误）
	if info.Size() == 0 {
		return fmt.Errorf("%w: %s为空文件: %s", ErrInvalidConfig, fileType, filePath)
	}

	return nil
}

// validateOutputPath 验证输出路径是否可写
// 功能: 检查输出目录是否存在且可写
// 参数:
//   - outputPath: 输出文件路径
//
// 返回值:
//   - error: 验证失败时的错误信息
func validateOutputPath(outputPath string) error {
	// 获取输出目录
	outputDir := filepath.Dir(outputPath)

	// 检查目录是否存在
	if _, err := os.Stat(outputDir); os.IsNotExist(err) {
		return fmt.Errorf("%w: 输出目录不存在: %s", ErrFileNotFound, outputDir)
	}

	// 检查目录写权限（通过创建临时文件测试）
	tempFile := filepath.Join(outputDir, ".stamp_tool_write_test")
	file, err := os.Create(tempFile)
	if err != nil {
		return fmt.Errorf("%w: 输出目录无写权限: %s, 错误: %v", ErrFileAccess, outputDir, err)
	}
	file.Close()
	os.Remove(tempFile) // 清理测试文件

	return nil
}

// validateFileExtension 验证文件扩展名
// 功能: 检查文件扩展名是否符合要求
// 参数:
//   - filePath: 文件路径
//   - fileType: 文件类型描述
//
// 返回值:
//   - error: 验证失败时的错误信息
func validateFileExtension(filePath, fileType string) error {
	ext := strings.ToLower(filepath.Ext(filePath))

	switch fileType {
	case "输入文件":
		if ext != ".pdf" {
			return fmt.Errorf("%w: 输入文件必须是PDF格式，当前格式: %s", ErrInvalidConfig, ext)
		}
	case "印章文件":
		validExts := []string{".png", ".jpg", ".jpeg", ".gif", ".bmp"}
		valid := false
		for _, validExt := range validExts {
			if ext == validExt {
				valid = true
				break
			}
		}
		if !valid {
			return fmt.Errorf("%w: 印章文件格式不支持: %s，支持格式: %v", ErrInvalidConfig, ext, validExts)
		}
	}

	return nil
}

// validateOutputFile 验证输出文件是否成功创建
// 功能: 检查输出文件是否存在且有效
// 参数:
//   - outputPath: 输出文件路径
//
// 返回值:
//   - error: 验证失败时的错误信息
func validateOutputFile(outputPath string) error {
	info, err := os.Stat(outputPath)
	if os.IsNotExist(err) {
		return fmt.Errorf("%w: 输出文件未成功创建: %s", ErrPDFProcessing, outputPath)
	}
	if err != nil {
		return fmt.Errorf("%w: 无法访问输出文件: %s, 错误: %v", ErrFileAccess, outputPath, err)
	}

	if info.Size() == 0 {
		return fmt.Errorf("%w: 输出文件为空: %s", ErrPDFProcessing, outputPath)
	}

	log.Printf("输出文件验证成功: %s (大小: %d 字节)", outputPath, info.Size())
	return nil
}

// filterPagesByRange 根据页面范围类型过滤页面
// 功能: 根据指定的页面范围类型（所有页面、奇数页、偶数页）过滤页面列表
// 参数:
//   - totalPages: PDF总页数
//   - rangeType: 页面范围类型
//
// 返回值:
//   - []int: 过滤后的页面列表
//   - error: 处理过程中的错误信息
func filterPagesByRange(totalPages int, rangeType PageRangeType) ([]int, error) {
	// 验证输入参数
	if totalPages <= 0 {
		return nil, fmt.Errorf("%w: 总页数必须大于0，当前值: %d", ErrInvalidRange, totalPages)
	}
	if !rangeType.IsValid() {
		return nil, fmt.Errorf("%w: 无效的页面范围类型: %d", ErrInvalidConfig, int(rangeType))
	}

	var pages []int

	// 根据范围类型过滤页面
	switch rangeType {
	case PageRangeAll:
		// 所有页面
		for i := 1; i <= totalPages; i++ {
			pages = append(pages, i)
		}
	case PageRangeOdd:
		// 仅奇数页
		for i := 1; i <= totalPages; i++ {
			if i%2 == 1 {
				pages = append(pages, i)
			}
		}
	case PageRangeEven:
		// 仅偶数页
		for i := 1; i <= totalPages; i++ {
			if i%2 == 0 {
				pages = append(pages, i)
			}
		}
	case PageRangeFirst:
		// 仅首页
		pages = append(pages, 1)
	case PageRangeLast:
		// 仅尾页
		pages = append(pages, totalPages)
	case PageRangeFirstLast:
		// 首页+尾页
		pages = append(pages, 1)
		if totalPages > 1 {
			pages = append(pages, totalPages)
		} else {
			// 如果总页数只有一页，在第一页盖两个章
			pages = append(pages, 1)
		}
	}

	// 4. 验证结果
	if len(pages) == 0 {
		return nil, fmt.Errorf("%w: 没有符合条件的页面，范围类型'%s'，总页数: %d", ErrInvalidRange, rangeType.String(), totalPages)
	}

	log.Printf("页面过滤完成: 范围类型=%s, 总页数=%d, 过滤后页数=%d", rangeType.String(), totalPages, len(pages))
	return pages, nil
}

// filterPagesBySelector 根据页面选择器过滤页面
// 功能: 根据PageSelector配置过滤出需要处理的页面列表，支持自定义页面选择
// 实现步骤:
//  1. 验证输入参数的有效性
//  2. 优先处理自定义页面选择（PageNumbers和PageRanges）
//  3. 如果没有自定义选择，回退到PageRangeType处理
//  4. 验证和去重页面列表
//  5. 返回排序后的页面列表
//
// 参数:
//   - totalPages: PDF文档总页数
//   - selector: 页面选择器配置
//
// 返回值:
//   - []int: 过滤后的页面列表（已排序去重）
//   - error: 处理过程中的错误信息
func filterPagesBySelector(totalPages int, selector PageSelector) ([]int, error) {
	// 1. 验证输入参数
	if totalPages <= 0 {
		return nil, fmt.Errorf("%w: 总页数必须大于0，当前值: %d", ErrInvalidRange, totalPages)
	}

	// 2. 如果有自定义页面选择，优先处理
	if selector.HasCustomSelection() {
		pageSet := make(map[int]bool) // 使用map去重

		// 处理具体页面列表
		for _, page := range selector.PageNumbers {
			if page < 1 || page > totalPages {
				return nil, fmt.Errorf("%w: 页面号%d超出有效范围[1-%d]", ErrInvalidRange, page, totalPages)
			}
			pageSet[page] = true
		}

		// 处理页面范围列表
		for _, pageRange := range selector.PageRanges {
			if !pageRange.IsValid() {
				return nil, fmt.Errorf("%w: 无效的页面范围[%d-%d]", ErrInvalidRange, pageRange.Start, pageRange.End)
			}
			if pageRange.Start > totalPages {
				return nil, fmt.Errorf("%w: 页面范围起始页%d超出总页数%d", ErrInvalidRange, pageRange.Start, totalPages)
			}
			// 调整结束页不超过总页数
			endPage := pageRange.End
			if endPage > totalPages {
				endPage = totalPages
			}
			for page := pageRange.Start; page <= endPage; page++ {
				pageSet[page] = true
			}
		}

		// 转换为排序的切片
		var pages []int
		for page := 1; page <= totalPages; page++ {
			if pageSet[page] {
				pages = append(pages, page)
			}
		}

		if len(pages) == 0 {
			return nil, fmt.Errorf("%w: 自定义页面选择没有匹配到任何有效页面", ErrInvalidRange)
		}

		log.Printf("页面过滤完成: 自定义选择, 总页数=%d, 过滤后页数=%d", totalPages, len(pages))
		return pages, nil
	}

	// 3. 回退到PageRangeType处理
	return filterPagesByRange(totalPages, selector.RangeType)
}

func filterNormalStampPagesBySelector(totalPages int, selector PageSelector) ([]int, error) {
	// 1. 验证输入参数
	if totalPages <= 0 {
		return nil, fmt.Errorf("%w: 总页数必须大于0，当前值: %d", ErrInvalidRange, totalPages)
	}

	// 2. 如果有自定义页面选择，优先处理
	if selector.HasCustomSelection() {
		pageSet := make(map[int]bool) // 使用map去重

		// 处理具体页面列表 - 取交集，只保留有效页面
		for _, page := range selector.PageNumbers {
			if page >= 1 && page <= totalPages {
				pageSet[page] = true
			}
		}

		// 处理页面范围列表 - 取交集，只保留有效页面
		for _, pageRange := range selector.PageRanges {
			if !pageRange.IsValid() {
				return nil, fmt.Errorf("%w: 无效的页面范围[%d-%d]", ErrInvalidRange, pageRange.Start, pageRange.End)
			}
			// 计算与总页数的交集
			startPage := pageRange.Start
			endPage := pageRange.End
			if startPage < 1 {
				startPage = 1
			}
			if endPage > totalPages {
				endPage = totalPages
			}
			// 只有当起始页不超过总页数且结束页不小于1时才有交集
			if startPage <= totalPages && endPage >= 1 {
				for page := startPage; page <= endPage; page++ {
					pageSet[page] = true
				}
			}
		}

		// 转换为排序的切片
		var pages []int
		for page := 1; page <= totalPages; page++ {
			if pageSet[page] {
				pages = append(pages, page)
			}
		}

		// 只有当交集为空时才报错
		if len(pages) == 0 {
			return nil, fmt.Errorf("%w: 用户指定的页面与总页数[1-%d]没有交集", ErrInvalidRange, totalPages)
		}

		log.Printf("页面过滤完成: 自定义选择, 总页数=%d, 过滤后页数=%d", totalPages, len(pages))
		return pages, nil
	}

	// 3. 回退到PageRangeType处理
	return filterPagesByRange(totalPages, selector.RangeType)
}

// calculateOptimizedRidingStampGroups 计算优化的骑缝章分组
// 功能: 根据总页数和间隔页数计算骑缝章分组，优化最后一组页数过少的情况，并处理特定的防重叠场景
// 参数:
//   - totalPages: PDF总页数
//   - interval: 骑缝章间隔页数，0表示单个骑缝章覆盖所有页面
//
// 返回值:
//   - []RidingStampGroup: 优化后的骑缝章分组列表
//   - error: 计算过程中的错误信息
func calculateOptimizedRidingStampGroups(totalPages, interval int) ([]RidingStampGroup, error) {
	// 验证输入参数
	if totalPages <= 0 || totalPages > 1000 {
		return nil, fmt.Errorf("%w: 总页数必须在1-1000之间，当前值: %d", ErrInvalidRange, totalPages)
	}
	if interval < 0 {
		return nil, fmt.Errorf("%w: 间隔页数不能为负数，当前值: %d", ErrInvalidConfig, interval)
	}

	// 如果间隔为0或大于等于总页数，创建单个分组覆盖所有页面
	if interval == 0 || interval >= totalPages {
		log.Printf("创建单个骑缝章分组: 总页数=%d, 间隔=%d", totalPages, interval)
		return []RidingStampGroup{{
			StartPage: 1,
			EndPage:   totalPages,
			Pages:     totalPages,
		}}, nil
	}

	// 骑缝章的正确逻辑：每个章都跨越interval页，可能会有重叠
	// 计算需要多少个章：从第1页开始，每interval页一个章
	var groups []RidingStampGroup

	// 创建标准的骑缝章组
	for startPage := 1; startPage <= totalPages; startPage += interval {
		endPage := startPage + interval - 1

		// 如果结束页超过总页数，需要向前合并
		if endPage > totalPages {
			// 向前合并：确保章跨越interval页
			endPage = totalPages
			startPage = totalPages - interval + 1
			if startPage < 1 {
				startPage = 1
			}
		}

		// 检查是否与已有分组重复
		duplicate := false
		for _, existingGroup := range groups {
			if existingGroup.StartPage == startPage && existingGroup.EndPage == endPage {
				duplicate = true
				break
			}
		}

		// 只有不重复的分组才添加
		if !duplicate {
			groups = append(groups, RidingStampGroup{
				StartPage: startPage,
				EndPage:   endPage,
				Pages:     endPage - startPage + 1,
			})
		}

		// 如果这个章已经覆盖到最后一页，就不需要再创建更多章了
		if endPage >= totalPages {
			break
		}
	}

	// 验证分组结果
	if len(groups) == 0 {
		return nil, fmt.Errorf("%w: 未能创建有效的骑缝章分组", ErrInvalidConfig)
	}

	log.Printf("骑缝章分组完成: 总页数=%d, 间隔=%d, 分组数=%d", totalPages, interval, len(groups))
	for i, group := range groups {
		log.Printf("章%d: 页面%d-%d (共%d页)", i+1, group.StartPage, group.EndPage, group.Pages)
	}

	return groups, nil
}

// calculateGroupPosition 计算分组位置偏移
// 功能: 根据分组索引动态计算位置偏移，防止多个骑缝章重叠
// 参数:
//   - groupIndex: 分组索引（从0开始）
//   - baseOffset: 基础偏移量 [x, y]
//   - stampHeight: 印章高度（用于计算垂直偏移）
//
// 返回值:
//   - []int32: 调整后的偏移量 [x, y]
//   - error: 计算过程中的错误信息
func calculateGroupPosition(groupIndex int, baseOffset []int32, stampWidth, stampHeight float64, ridingStampPosition RidingStampPosition) ([]int32, error) {
	// 计算位置偏移策略：
	// 1. 第一个分组使用原始偏移
	// 2. 后续分组根据ridingStampPosition的值确定偏移方向：
	//    - t或b：向右偏移一个印章宽度
	//    - l或r：向下偏移一个印章高度

	offsetX := baseOffset[0]
	offsetY := baseOffset[1]

	// 如果是第一个分组，直接使用基础偏移
	if groupIndex == 0 {
		log.Printf("分组%d位置计算: 使用基础偏移 [%d, %d]", groupIndex, offsetX, offsetY)
		return []int32{offsetX, offsetY}, nil
	}

	// 为后续分组计算偏移：根据骑缝章位置确定偏移方向
	horizontalOffset := float64(offsetX)
	verticalOffset := float64(offsetY)

	// 根据ridingStampPosition确定偏移方向
	// 精确计算：实现真正的紧密贴合，第二张图片紧贴第一张图片边缘
	switch ridingStampPosition {
	case RidingStampPositionTop, RidingStampPositionBottom:
		// t或b：第二张图片与第一张图片水平方向无间隙贴合
		// 使用极小偏移实现轻微重叠，消除视觉间隙
		horizontalOffset += stampWidth
	case RidingStampPositionLeft, RidingStampPositionRight:
		// l或r：第二张图片与第一张图片垂直方向无间隙贴合
		// 使用极小偏移实现轻微重叠，消除视觉间隙
		verticalOffset -= stampHeight
	default:
		return nil, fmt.Errorf("%w: 不支持的骑缝章位置: %s", ErrInvalidConfig, ridingStampPosition)
	}

	// 转换为int32并返回
	newOffsetX := int32(horizontalOffset)
	newOffsetY := int32(verticalOffset)

	log.Printf("分组%d位置计算: 基础偏移[%d, %d] -> 调整后偏移[%d, %d]，印章尺寸=%.2fx%.2f",
		groupIndex, offsetX, offsetY, newOffsetX, newOffsetY, stampWidth, stampHeight)

	return []int32{newOffsetX, newOffsetY}, nil
}

// splitStampImageForTool 将印章图片垂直切分成多个片段
// 功能: 将原始印章按页数垂直分割，每页使用一个片段实现真正的骑缝章效果
// 参数:
//   - stampPath: 原始印章图片路径
//   - pages: 总页数
//
// 返回值:
//   - []string: 切分后的图片文件路径列表
//   - error: 处理过程中的错误信息
//
// 异常: 图片读取失败、图片保存失败
// splitStampImageForTool 切分印章图片为多个片段
// 参数:
//   - stampPath: 印章图片文件路径
//   - pages: 需要切分的页数
//   - rotation: 旋转角度（度数，-180到180）
//
// 返回值:
//   - []string: 切分后的图片文件路径列表
//   - error: 错误信息
//
// 功能:
//  1. 验证输入参数
//  2. 加载并解码原始印章图片
//  3. 如果有旋转角度，先旋转整个图片
//  4. 按页数垂直切分图片
//  5. 保存每个切分片段为临时文件
func splitStampImageForTool(stampPath string, ridingStampPosition RidingStampPosition, pages int, rotation float64) ([]string, error) {
	// 1. 验证输入参数
	if pages <= 0 {
		return nil, fmt.Errorf("%w: 页数必须大于0，当前值: %d", ErrInvalidRange, pages)
	}
	if pages > 1000 {
		return nil, fmt.Errorf("%w: 页数过多(>1000)，当前值: %d", ErrInvalidRange, pages)
	}
	if rotation < -180 || rotation > 180 {
		return nil, fmt.Errorf("%w: 旋转角度必须在-180到180度之间，当前值: %.1f", ErrInvalidRange, rotation)
	}
	if ridingStampPosition == "" {
		return nil, fmt.Errorf("%w: 骑缝章的盖章位置不能为空", ErrInvalidConfig)
	}
	// 验证骑缝章位置是否有效
	switch ridingStampPosition {
	case RidingStampPositionLeft, RidingStampPositionRight, RidingStampPositionTop, RidingStampPositionBottom:
		// 有效位置，继续处理
	default:
		return nil, fmt.Errorf("%w: 不支持的骑缝章位置: %s", ErrInvalidConfig, ridingStampPosition)
	}

	// 2. 打开原始印章图片
	file, err := os.Open(stampPath)
	if err != nil {
		return nil, fmt.Errorf("%w: 打开印章图片失败: %v", ErrImageProcessing, err)
	}
	defer func() {
		if closeErr := file.Close(); closeErr != nil {
			log.Printf("警告: 关闭印章图片文件失败: %v", closeErr)
		}
	}()

	// 3. 解码图片
	originalImg, format, err := image.Decode(file)
	if err != nil {
		return nil, fmt.Errorf("%w: 解码印章图片失败: %v", ErrImageProcessing, err)
	}

	log.Printf("开始处理印章图片: 格式=%s, 页数=%d, 旋转角度=%.1f°", format, pages, rotation)

	// 4. 如果需要旋转，先旋转整个图片
	processedImg := originalImg
	if rotation != 0 {
		// 使用透明背景进行旋转
		processedImg = imaging.Rotate(originalImg, rotation, image.Transparent)
		log.Printf("印章图片已旋转 %.1f°", rotation)
	}

	// 5. 获取处理后图片的尺寸
	dimensions := getImageDimensions(processedImg)

	// 6. 计算切割配置
	cutConfig := calculateCutConfig(dimensions, ridingStampPosition, pages)

	// 7. 创建印章片段
	segmentPaths, err := createImageSegments(processedImg, cutConfig, pages)
	if err != nil {
		return nil, err
	}

	// 8. 根据骑缝章位置调整片段顺序
	adjustSegmentOrder(segmentPaths, ridingStampPosition)

	return segmentPaths, nil
}

// getImageDimensions 获取图片尺寸信息
// 参数:
//   - img: 图片对象
//
// 返回值:
//   - ImageDimensions: 包含宽度和高度的结构体
func getImageDimensions(img image.Image) ImageDimensions {
	bounds := img.Bounds()
	return ImageDimensions{
		Width:  bounds.Dx(),
		Height: bounds.Dy(),
	}
}

// calculateCutConfig 计算切割配置
// 参数:
//   - dimensions: 图片尺寸信息
//   - ridingStampPosition: 骑缝章位置
//   - pages: 页数
//
// 返回值:
//   - CutConfig: 切割配置信息
func calculateCutConfig(dimensions ImageDimensions, ridingStampPosition RidingStampPosition, pages int) CutConfig {
	var config CutConfig

	// 判断切割方向
	switch ridingStampPosition {
	case RidingStampPositionLeft, RidingStampPositionRight:
		// 横向切割 ：用于 横向摆放 的骑缝章（顶部/底部位置），需要沿X轴（宽度方向）分割
		config.IsHorizontalCut = true
		config.SegmentWidth = dimensions.Width / pages
		config.SegmentHeight = dimensions.Height
		if config.SegmentWidth == 0 {
			config.SegmentWidth = 1 // 防止宽度为0
		}
		log.Printf("骑缝章位置为%s，采用横向切割，每片段宽度: %d像素", ridingStampPosition, config.SegmentWidth)
	case RidingStampPositionTop, RidingStampPositionBottom:
		// 纵向切割 ：用于 纵向摆放 的骑缝章（左侧/右侧位置），需要沿Y轴（高度方向）分割
		config.IsHorizontalCut = false
		config.SegmentWidth = dimensions.Width
		config.SegmentHeight = dimensions.Height / pages
		if config.SegmentHeight == 0 {
			config.SegmentHeight = 1 // 防止高度为0
		}
		log.Printf("骑缝章位置为%s，采用纵向切割，每片段高度: %d像素", ridingStampPosition, config.SegmentHeight)
	}

	return config
}

// createImageSegments 创建图片片段
// 参数:
//   - processedImg: 处理后的图片
//   - cutConfig: 切割配置
//   - pages: 页数
//
// 返回值:
//   - []string: 片段文件路径列表
//   - error: 错误信息
func createImageSegments(processedImg image.Image, cutConfig CutConfig, pages int) ([]string, error) {
	dimensions := getImageDimensions(processedImg)

	// 根据切割方向选择对应的创建函数
	if cutConfig.IsHorizontalCut {
		return createHorizontalSegments(processedImg, dimensions, cutConfig, pages)
	}
	return createVerticalSegments(processedImg, dimensions, cutConfig, pages)
}

// createHorizontalSegments 创建横向切割的图片片段
// 参数:
//   - processedImg: 处理后的图片
//   - dimensions: 图片尺寸
//   - cutConfig: 切割配置
//   - pages: 页数
//
// 返回值:
//   - []string: 片段文件路径列表
//   - error: 错误信息
func createHorizontalSegments(processedImg image.Image, dimensions ImageDimensions, cutConfig CutConfig, pages int) ([]string, error) {
	var segmentPaths []string

	for i := 0; i < pages; i++ {
		// 计算横向切割的坐标
		startX := i * cutConfig.SegmentWidth
		endX := startX + cutConfig.SegmentWidth

		// 确保最后一个片段不超出原图边界
		if endX > dimensions.Width {
			endX = dimensions.Width
		}

		// 计算实际尺寸
		actualWidth := cutConfig.SegmentWidth
		actualHeight := cutConfig.SegmentHeight
		if i == pages-1 && endX < startX+cutConfig.SegmentWidth {
			// 只有当最后片段确实不足时才调整
			actualWidth = endX - startX
		}

		// 定义源图像和目标图像的矩形区域
		srcRect := image.Rect(startX, 0, endX, dimensions.Height)
		dstRect := image.Rect(0, 0, actualWidth, actualHeight)

		// 创建并保存片段
		segmentPath, err := createAndSaveSegment(processedImg, srcRect, dstRect, actualWidth, actualHeight, i+1, pages)
		if err != nil {
			return nil, err
		}
		segmentPaths = append(segmentPaths, segmentPath)
	}

	return segmentPaths, nil
}

// createVerticalSegments 创建纵向切割的图片片段
// 参数:
//   - processedImg: 处理后的图片
//   - dimensions: 图片尺寸
//   - cutConfig: 切割配置
//   - pages: 页数
//
// 返回值:
//   - []string: 片段文件路径列表
//   - error: 错误信息
func createVerticalSegments(processedImg image.Image, dimensions ImageDimensions, cutConfig CutConfig, pages int) ([]string, error) {
	var segmentPaths []string

	for i := 0; i < pages; i++ {
		// 计算纵向切割的坐标
		startY := i * cutConfig.SegmentHeight
		endY := startY + cutConfig.SegmentHeight

		// 确保最后一个片段不超出原图边界
		if endY > dimensions.Height {
			endY = dimensions.Height
		}

		// 计算实际尺寸
		actualWidth := cutConfig.SegmentWidth
		actualHeight := cutConfig.SegmentHeight
		if i == pages-1 && endY < startY+cutConfig.SegmentHeight {
			// 只有当最后片段确实不足时才调整
			actualHeight = endY - startY
		}

		// 定义源图像和目标图像的矩形区域
		srcRect := image.Rect(0, startY, dimensions.Width, endY)
		dstRect := image.Rect(0, 0, actualWidth, actualHeight)

		// 创建并保存片段
		segmentPath, err := createAndSaveSegment(processedImg, srcRect, dstRect, actualWidth, actualHeight, i+1, pages)
		if err != nil {
			return nil, err
		}
		segmentPaths = append(segmentPaths, segmentPath)
	}

	return segmentPaths, nil
}

// createAndSaveSegment 创建并保存单个图片片段
// 参数:
//   - processedImg: 处理后的图片
//   - srcRect: 源图像矩形区域
//   - dstRect: 目标图像矩形区域
//   - actualWidth: 实际宽度
//   - actualHeight: 实际高度
//   - segmentIndex: 片段索引（从1开始）
//   - totalPages: 总页数
//
// 返回值:
//   - string: 片段文件路径
//   - error: 错误信息
func createAndSaveSegment(processedImg image.Image, srcRect, dstRect image.Rectangle, actualWidth, actualHeight, segmentIndex, totalPages int) (string, error) {
	// 创建新的图片用于存储当前片段
	segmentImg := image.NewRGBA(image.Rect(0, 0, actualWidth, actualHeight))

	// 将处理后图片的指定区域绘制到新图片上
	draw.Draw(segmentImg, dstRect, processedImg, srcRect.Min, draw.Src)

	// 生成片段文件名
	segmentPath := fmt.Sprintf("seal_segment_%d.png", segmentIndex)

	// 保存片段图片
	segmentFile, err := os.Create(segmentPath)
	if err != nil {
		return "", fmt.Errorf("%w: 创建片段文件失败: %v", ErrImageProcessing, err)
	}

	err = png.Encode(segmentFile, segmentImg)
	closeErr := segmentFile.Close()
	if err != nil {
		return "", fmt.Errorf("%w: 保存片段图片失败: %v", ErrImageProcessing, err)
	}
	if closeErr != nil {
		log.Printf("警告: 关闭片段文件失败: %v", closeErr)
	}

	log.Printf("创建印章片段 %d/%d: %s (宽度: %d像素, 高度: %d像素)", segmentIndex, totalPages, filepath.Base(segmentPath), actualWidth, actualHeight)

	return segmentPath, nil
}

// adjustSegmentOrder 根据骑缝章位置调整片段顺序
// 参数:
//   - segmentPaths: 片段文件路径列表
//   - ridingStampPosition: 骑缝章位置
func adjustSegmentOrder(segmentPaths []string, ridingStampPosition RidingStampPosition) {
	switch ridingStampPosition {
	case RidingStampPositionLeft, RidingStampPositionTop:
		// 左侧或顶部位置需要颠倒顺序
		slices.Reverse(segmentPaths)
		log.Printf("骑缝章位置为%s，已颠倒片段顺序", ridingStampPosition)
	case RidingStampPositionRight, RidingStampPositionBottom:
		// 右侧或底部位置保持原顺序
		log.Printf("骑缝章位置为%s，保持原片段顺序", ridingStampPosition)
	}
}

// ImageDimensions 图片尺寸信息
type ImageDimensions struct {
	Width  int // 图片宽度
	Height int // 图片高度
}

// CutConfig 切割配置信息
type CutConfig struct {
	IsHorizontalCut bool // 是否为横向切割
	SegmentWidth    int  // 片段宽度
	SegmentHeight   int  // 片段高度
}
